package com.mzplayer.videoview;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.BatteryManager;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;

import com.mzplayer.player.IJKMediaPlayer;
import com.mzplayer.player.MediaPlayer;
import com.mzplayer.utils.RS;
import com.mzplayer.utils.Util;
import com.mzplayer.videoview.base.EasyParent;
import com.mzplayer.widget.AutoMarqueeTextView;
import com.mzplayer.widget.ShowContainer;

import java.util.Locale;

public class EasyVideoView extends EasyParent {
    private FrameLayout controller;
    private ImageView controller_unlock;
    private ImageView controller_lock;
    private LinearLayout controller_bottom;
    private SeekBar controller_bottom_seekbar;
    private Button controller_bottom_play;
    private LinearLayout controller_bottom_left_diy;
    private TextView controller_bottom_flag;
    private LinearLayout controller_bottom_right_diy;
    private LinearLayout controller_top;
    private Button controller_bottom_goto_full;
    private Button controller_top_tiny_resume;
    private Button controller_top_back;
    private AutoMarqueeTextView controller_top_title;
    private LinearLayout controller_top_right_diy;
    private LinearLayout controller_top_bt;
    private ProgressBar controller_top_battery;
    private TextView controller_top_system_time;
    private Button controller_top_tiny_close;

    private LinearLayout loading;
    private LinearLayout seek;
    private LinearLayout vl;
    private TextView loading_flag;
    private ImageView seek_img;
    private TextView seek_flag;
    private ImageView vl_img;
    private ProgressBar vl_progress;
    private TextView errorView;
    private BatteryBroadcastReceiver batteryBroadcastReceiver;

    public EasyVideoView(Context context) {
        this(context, null);
    }

    public EasyVideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public EasyVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void initResource(Context context) {
        RS.init(context);
    }

    @Override
    protected int getLayoutID() {
        return RS.layout.mz_controller;
    }

    @Override
    protected int getBackgroundColor() {
        return Util.getResourcesColor(context, RS.color.ctl_bg);
    }

    @Override
    protected void initViews() {
        controller = findViewById(RS.id.controller);
        controller_unlock = findViewById(RS.id.controller_unlock);
        controller_lock = findViewById(RS.id.controller_lock);
        controller_bottom = findViewById(RS.id.controller_bottom);
        controller_bottom_seekbar = findViewById(RS.id.controller_bottom_seekbar);
        controller_bottom_play = findViewById(RS.id.controller_bottom_play);
        controller_bottom_left_diy = findViewById(RS.id.controller_bottom_left_diy);
        controller_bottom_flag = findViewById(RS.id.controller_bottom_flag);
        controller_bottom_right_diy = findViewById(RS.id.controller_bottom_right_diy);
        controller_bottom_goto_full = findViewById(RS.id.controller_bottom_goto_full);
        controller_top = findViewById(RS.id.controller_top);
        controller_top_tiny_resume = findViewById(RS.id.controller_top_tiny_resume);
        controller_top_back = findViewById(RS.id.controller_top_back);
        controller_top_title = findViewById(RS.id.controller_top_title);
        controller_top_right_diy = findViewById(RS.id.controller_top_right_diy);
        controller_top_bt = findViewById(RS.id.controller_top_bt);
        controller_top_battery = findViewById(RS.id.controller_top_battery);
        controller_top_system_time = findViewById(RS.id.controller_top_system_time);
        controller_top_tiny_close = findViewById(RS.id.controller_top_tiny_close);

        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
        loading = (LinearLayout) inflate(context, RS.layout.mz_loading, null);
        loading.setLayoutParams(layoutParams);
        seek = (LinearLayout) inflate(context, RS.layout.mz_seek, null);
        seek.setLayoutParams(layoutParams);
        vl = (LinearLayout) inflate(context, RS.layout.mz_vl, null);
        vl.setLayoutParams(layoutParams);
        loading_flag = loading.findViewById(RS.id.loading_flag);
        seek_img = seek.findViewById(RS.id.seek_img);
        seek_flag = seek.findViewById(RS.id.seek_flag);
        vl_img = vl.findViewById(RS.id.vl_img);
        vl_progress = vl.findViewById(RS.id.vl_progress);

        errorView = new TextView(context);
        errorView.setLayoutParams(layoutParams);
        int pw = (int) getResources().getDimension(RS.dimen.seek_padding_w);
        int ph = (int) getResources().getDimension(RS.dimen.seek_padding_h);
        errorView.setPadding(pw, ph, pw, ph);
        errorView.setBackgroundResource(RS.drawable.mz_selector_option_bg);
        errorView.setTextColor(Util.getResourcesColor(context, RS.color.ctl_option));
        errorView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(RS.dimen.option_font_size));
    }

    @Override
    protected void initListener() {
        controller_bottom_play.setOnClickListener(this);
        controller_top_tiny_resume.setOnClickListener(this);
        controller_top_tiny_close.setOnClickListener(this);
        controller_top_back.setOnClickListener(this);
        controller_bottom_goto_full.setOnClickListener(this);
        controller_lock.setOnClickListener(this);
        controller_unlock.setOnClickListener(this);
        controller_bottom_seekbar.setOnSeekBarChangeListener(this);
    }


    @Override
    protected void lock() {
        controller_top.setVisibility(GONE);
        controller_lock.setVisibility(GONE);
        controller_unlock.setVisibility(VISIBLE);
        controller_bottom.setVisibility(GONE);

    }

    @Override
    protected void unlock() {
        controller_top.setVisibility(VISIBLE);
        controller_lock.setVisibility(VISIBLE);
        controller_unlock.setVisibility(GONE);
        controller_bottom.setVisibility(VISIBLE);

    }

    @Override
    protected void setTitle(String title) {
        controller_top_title.setText(title);
    }

    private void add(View view) {
        remove(view);
        addView(view);
    }

    /**
     * 由于lock和onToggle方法也在设置View的显示状态
     * 普通显示隐藏View会增加些不必要的代码
     * 所以这里直接设置View的宽高来实现显示隐藏
     *
     * @param view
     */
    private void showView(View view) {
        Object tag = view.getTag();
        if (tag != null) {
            ViewGroup.LayoutParams params = view.getLayoutParams();
            int[] size = (int[]) tag;
            params.width = size[0];
            params.height = size[1];
            view.setLayoutParams(params);
            view.setTag(null);
        }
    }

    private void hideView(View view) {
        if (view.getTag() == null) {
            ViewGroup.LayoutParams params = view.getLayoutParams();
            view.setTag(new int[]{params.width, params.height});
            params.width = 0;
            params.height = 0;
            view.setLayoutParams(params);
        }
    }

    @Override
    protected void showError(StringBuilder err) {
        errorView.setText(err);
        add(errorView);
        if (callBack != null) {
            callBack.onError(err.toString());
        }
    }

    @Override
    protected void hideError() {
        remove(errorView);
    }

    @Override
    protected void showSeekBar() {
        showView(controller_bottom_seekbar);
    }

    @Override
    protected void hideSeekBar() {
        hideView(controller_bottom_seekbar);
    }

    @Override
    protected void onPlayTimeFlush(boolean isLive, String currentTime, String maxTime) {
        StringBuilder flag = new StringBuilder();
        if (isLive) {
            flag.append("直播中");
        } else {
            flag.append(currentTime).append("/").append(maxTime);
        }
        controller_bottom_flag.setText(flag);
    }

    @Override
    protected void onSystemTimeFlush(String format) {
        controller_top_system_time.setText(format);
    }

    @Override
    protected void setSeekBarMax(int max) {
        controller_bottom_seekbar.setMax(max);
    }

    @Override
    protected void setSeekBarProgress(int progress) {
        controller_bottom_seekbar.setProgress(progress);
    }

    @Override
    protected void setSeekBarSecondaryProgress(int secondaryProgress) {
        controller_bottom_seekbar.setSecondaryProgress(secondaryProgress);
    }

    @Override
    protected void showLoading(String flag) {
        loading_flag.setText(flag);
        add(loading);
    }

    @Override
    protected void hideLoading() {
        remove(loading);
    }

    @Override
    protected void onLoadingFlush() {
        loading_flag.setText(new StringBuilder("正在缓冲 ").append(getLoadingPercent()).append("% (").append(Util.SizeFormat(getTcpSpeed())).append("/s)"));
    }

    @Override
    protected void showBright(int position, int max) {
        vl_img.setBackgroundResource(RS.drawable.mz_bg_bright);
        vl_progress.setMax(max);
        vl_progress.setProgress(position);
        add(vl);
    }

    @Override
    protected void hideBright() {
        remove(vl);
    }

    @Override
    protected void onBrightFlush(int position) {
        vl_progress.setProgress(position);
    }

    @Override
    protected void showVolume(int position, int max) {
        vl_img.setBackgroundResource(position > 0 ? RS.drawable.mz_bg_volume : RS.drawable.mz_bg_volume_close);
        vl_progress.setMax(max);
        vl_progress.setProgress(position);
        add(vl);
    }

    @Override
    protected void hideVolume() {
        remove(vl);
    }

    @Override
    protected void onVolumeFlush(int position) {
        vl_img.setBackgroundResource(position > 0 ? RS.drawable.mz_bg_volume : RS.drawable.mz_bg_volume_close);
        vl_progress.setProgress(position);
    }

    @Override
    protected void showSeek(String currentTime, String maxTime) {
        seek_flag.setText(new StringBuilder(currentTime).append("/").append(maxTime));
        seek_img.setImageResource(RS.drawable.mz_bg_play_go);
        add(seek);
    }

    @Override
    protected void hideSeek() {
        remove(seek);
    }

    @Override
    protected void onSeekFlush(boolean toEnd, String currentTime, String maxTime) {
        seek_flag.setText(new StringBuilder(currentTime).append("/").append(maxTime));
        seek_img.setImageResource(toEnd ? RS.drawable.mz_bg_play_go : RS.drawable.mz_bg_play_back);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && getScreenState() == SCREEN_FULL) {
            if (callBack != null) {
                callBack.onFullKeyBackDown();
            }
            return true;
        }
        return false;
    }

    @Override
    public void onClick(View v) {
        if (v == controller_bottom_play) {
            doPauseAndPlay();
        } else if (v == controller_top_tiny_resume) {
            toggleNormal();
            Activity activity = Util.scanForActivity(getContext());
            Intent intent = new Intent(activity, activity.getClass());
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            activity.startActivity(intent);
        } else if (v == controller_top_tiny_close) {
            pause();
            toggleNormal();
        } else if (v == controller_top_back) {
            if (getScreenState() == SCREEN_FULL) {
                if (callBack != null) {
                    callBack.onFullBackClick();
                }
            } else if (getScreenState() == SCREEN_NORMAL) {
                if (callBack != null) {
                    callBack.onNormalBackClick();
                }
            }
        } else if (v == controller_bottom_goto_full) {
            toggleFull();
        } else if (v == controller_lock) {
            lock();
        } else if (v == controller_unlock) {
            unlock();
        }
    }

    @Override
    public boolean isShowing() {
        return controller.getVisibility() == VISIBLE;
    }

    @Override
    protected boolean isLocked() {
        return controller_unlock.getVisibility() == VISIBLE;
    }

    @Override
    public void show() {
        controller.setVisibility(VISIBLE);
        regBatteryBroadcastReceiver();
    }

    @Override
    public void hide() {
        controller.setVisibility(GONE);
        unRegBatteryBroadcastReceiver();
    }

    private void regBatteryBroadcastReceiver() {
        if (batteryBroadcastReceiver != null) {
            return;
        }
        batteryBroadcastReceiver = new BatteryBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        context.registerReceiver(batteryBroadcastReceiver, intentFilter);
    }

    private void unRegBatteryBroadcastReceiver() {
        if (batteryBroadcastReceiver == null) {
            return;
        }
        try {
            context.unregisterReceiver(batteryBroadcastReceiver);
            batteryBroadcastReceiver = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onToggleFull() {
        controller_lock.setVisibility(VISIBLE);
        controller_bottom_seekbar.setVisibility(VISIBLE);
        controller_bottom_left_diy.setVisibility(VISIBLE);
        controller_bottom_flag.setVisibility(VISIBLE);
        controller_bottom_right_diy.setVisibility(VISIBLE);
        controller_bottom_goto_full.setVisibility(GONE);
        controller_top_tiny_resume.setVisibility(GONE);
        controller_top_back.setVisibility(VISIBLE);
        controller_top_title.setVisibility(VISIBLE);
        controller_top_right_diy.setVisibility(VISIBLE);
        controller_top_bt.setVisibility(VISIBLE);
        controller_top_tiny_close.setVisibility(GONE);
        if (callBack != null) {
            callBack.onToggleFull();
        }
    }

    @Override
    protected void onToggleNormal() {
        controller_lock.setVisibility(GONE);
        controller_bottom_seekbar.setVisibility(VISIBLE);
        controller_bottom_left_diy.setVisibility(VISIBLE);
        controller_bottom_flag.setVisibility(VISIBLE);
        controller_bottom_right_diy.setVisibility(VISIBLE);
        controller_bottom_goto_full.setVisibility(VISIBLE);
        controller_top_tiny_resume.setVisibility(GONE);
        controller_top_back.setVisibility(VISIBLE);
        controller_top_title.setVisibility(VISIBLE);
        controller_top_right_diy.setVisibility(VISIBLE);
        controller_top_bt.setVisibility(GONE);
        controller_top_tiny_close.setVisibility(GONE);
        if (callBack != null) {
            callBack.onToggleNormal();
        }
    }

    @Override
    protected void onToggleFloat() {
        controller_lock.setVisibility(GONE);
        controller_bottom_seekbar.setVisibility(GONE);
        controller_bottom_left_diy.setVisibility(GONE);
        controller_bottom_flag.setVisibility(GONE);
        controller_bottom_right_diy.setVisibility(GONE);
        controller_bottom_goto_full.setVisibility(GONE);
        controller_top_tiny_resume.setVisibility(VISIBLE);
        controller_top_back.setVisibility(GONE);
        controller_top_title.setVisibility(INVISIBLE);
        controller_top_right_diy.setVisibility(GONE);
        controller_top_bt.setVisibility(GONE);
        controller_top_tiny_close.setVisibility(VISIBLE);
        if (callBack != null) {
            callBack.onToggleFloat();
        }
    }

    @Override
    protected MediaPlayer createPlayer() {
        return new IJKMediaPlayer(context);
    }

    @Override
    protected void onPlaying() {
        controller_bottom_play.setBackgroundResource(RS.drawable.mz_selector_pause);
    }

    @Override
    protected void onPaused() {
        controller_bottom_play.setBackgroundResource(RS.drawable.mz_selector_play);
    }

    @Override
    protected void onCompletion() {
        show(defaultDelay);
        if (callBack != null) {
            callBack.onCompletion();
        }
    }

    @Override
    protected void onTimedText(String text) {

    }

    class BatteryBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
                int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
                if (status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL) {
                    controller_top_battery.setProgress(0);
                    controller_top_battery.setSecondaryProgress(0);
                    controller_top_battery.setBackgroundResource(RS.drawable.mz_bg_battery_charge);
                } else {
                    int percent = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
                    controller_top_battery.setBackgroundResource(RS.drawable.mz_bg_battery);
                    if (percent > 20) {
                        controller_top_battery.setProgress(percent);
                    } else {
                        controller_top_battery.setProgress(0);
                        controller_top_battery.setSecondaryProgress(percent);
                    }
                }
            }
        }
    }

    private VideoViewCallBack callBack;
    private final ShowContainer showContainer = new ShowContainer(this);
    private int TRMarginLeft = (int) getResources().getDimension(RS.dimen.option_margin);
    private int BLMarginLeft = (int) getResources().getDimension(RS.dimen.option_margin_small);
    private int BRMarginLeft = TRMarginLeft;
    private TextView speedView;
    private TextView tmpView;

    public void showView(Object obj) {
        View view = Util.getView(obj);
        if (view == null) {
            return;
        }
        view.setVisibility(View.VISIBLE);
    }

    public void hideView(Object obj) {
        View view = Util.getView(obj);
        if (view == null) {
            return;
        }
        view.setVisibility(View.GONE);
    }

    public void setDiyLeftMargin(int index, int margin) {
        switch (index) {
            case 0:
                TRMarginLeft = margin;
                break;
            case 1:
                BLMarginLeft = margin;
                break;
            case 2:
                BRMarginLeft = margin;
                break;
        }
    }

    public void setViewState(int index, boolean show) {
        switch (index) {
            case 0:
                if (show) {
                    showView(controller_top_right_diy);
                } else {
                    hideView(controller_top_right_diy);
                }
                break;
            case 1:
                if (show) {
                    showView(controller_bottom_left_diy);
                } else {
                    hideView(controller_bottom_left_diy);
                }
                break;
            case 2:
                if (show) {
                    showView(controller_bottom_right_diy);
                } else {
                    hideView(controller_bottom_right_diy);
                }
                break;
            case 3:
                if (show) {
                    showView(controller_bottom_goto_full);
                } else {
                    hideView(controller_bottom_goto_full);
                }
                break;
            case 4:
                if (show) {
                    showView(controller_top);
                } else {
                    hideView(controller_top);
                }
                break;
            case 5:
                if (show) {
                    showView(controller_bottom);
                } else {
                    hideView(controller_bottom);
                }
                break;
        }
    }

    public void setCallBack(VideoViewCallBack callBack) {
        this.callBack = callBack;
    }

    public void addSpeed(int index) {
        speedView = new TextView(context);
        speedView.setText("倍速");
        LinearLayout value = new LinearLayout(context);
        value.setOrientation(LinearLayout.VERTICAL);
        ViewGroup.LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        value.setLayoutParams(layoutParams);
        LinearLayout.LayoutParams childLL = new LinearLayout.LayoutParams(Util.dip2px(context, 120), LayoutParams.WRAP_CONTENT, 1);
        value.addView(getTextView(2.0f, childLL));
        value.addView(getTextView(1.5f, childLL));
        value.addView(getTextView(1.25f, childLL));
        tmpView = getTextView(1.0f, childLL);
        tmpView.setTextColor(Util.getResourcesColor(context, RS.color.ctl_fore));
        tmpView.setEnabled(false);
        value.addView(tmpView);
        value.addView(getTextView(0.75f, childLL));
        value.addView(getTextView(0.5f, childLL));
        addOption(index, speedView, value);
    }

    private TextView getTextView(float speed, LinearLayout.LayoutParams LL) {
        TextView textView = new TextView(context);
        textView.setText(String.format(Locale.CHINA, "%.2fX", speed));
        textView.setTextColor(Util.getResourcesColor(context, RS.color.ctl_option));
        textView.setGravity(Gravity.CENTER);
        textView.setLayoutParams(LL);
        textView.setTag(speed);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (v != tmpView) {
                    if (tmpView != null) {
                        tmpView.setTextColor(Util.getResourcesColor(context, RS.color.ctl_option));
                        tmpView.setEnabled(true);
                    }
                    tmpView = (TextView) v;
                    tmpView.setTextColor(Util.getResourcesColor(context, RS.color.ctl_fore));
                    float speed = (float) tmpView.getTag();
                    if (speed == 1.00f) {
                        speedView.setText("倍速");
                    } else {
                        speedView.setText(tmpView.getText());
                    }
                    tmpView.setEnabled(false);
                    setSpeed(speed);
                }
            }
        });
        return textView;
    }

    public void addToggleFloat(int index) {
        ImageView toggleFloat = new ImageView(context);
        toggleFloat.setBackgroundResource(RS.drawable.mz_selector_to_tiny);
        toggleFloat.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleFloat();
            }
        });
        addOption(index, toggleFloat, null);
    }

    public void addOption(int index, Object key, Object value) {
        showContainer.addOption(index == 0 ? controller_top_right_diy : index == 1 ? controller_bottom_left_diy : controller_bottom_right_diy, index == 0 ? TRMarginLeft : index == 1 ? BLMarginLeft : BRMarginLeft, key, value);
    }

}
